using System;
using System.Collections;
using System.Configuration;
using System.Reflection;
using System.Web.UI.WebControls;
using Sedna.Core.Common.Objects.Navigation;
using Sedna.Core.Controller.Configurations;
using Sedna.Core.Globalization;
using Sedna.Core.Security;
using Sedna.Util;

namespace Sedna.Core.Controller
{
	public class GenericConfiguration : IConfiguration
	{

		private string id;
		private string objectName;
		private IDictionary actions;
		private IList exceptionHandlers;
		private IExceptionHandlerMatcher exceptionHandlerMatcher;
		private IList rolesVisible;
		private IList rolesEnabled;
		private IPrincipalWrapper principalWrapper;
		private IDictionary clientAttributes;
		private IMessageManager messageManager;
		private IImageManager imageManager;
		private bool causesValidation = false;
		private IList validatorWrappers;
		private Type controlType;
		private string label;
		private string labelKey;
		private IDictionary labels;
		private string executionContextPrefix;
		private string textKey;
		private Unit width;
		private Unit height;
		private string cssClass = null;
	    
		private IDataTranslator dataTranslator;
		private IDataTranslator dataParser;

        private IDictionary propertyDataTranslators;
        private IDictionary propertyDataParsers;

		private bool visible=true;
		private bool enabled=true;

        private string validationGroup = string.Empty;

		private string textBindPath;
		private string textUnbindPath;
		private string textKeyBindPath;
		private string textKeyUnbindPath;
		private string visibleBindPath;
		private string visibleUnbindPath;
		private string enabledBindPath;
		private string enabledUnbindPath;
		private string causesValidationBindPath;
		private string causesValidationUnbindPath;
		private string valueBindPath;
		private string valueUnbindPath;
        private string validationGroupBindPath = null;
        private string validationGroupUnbindPath = null;
        private bool readOnly;
        private string readOnlyBindPath;
        private string readOnlyUnbindPath;

        private IScopePathParser scopePathParser;
	    

	    /// <summary>
	    /// A list of properties that should not be unbinded for the first time
	    /// </summary>
        private IList allowFirstUnbindFor = new ArrayList();
	    
	    private bool doBind = true;	    
	    private bool doUnbind = true;

        private String doBindPath;
        private String doUnbindPath;

		private String contentPlaceHolderId;
        private string toolTip;
        private string toolTipKey;
	    private string tooltipUnbindPath;
	    private string tooltipBindPath;
	    private string tooltipKeyUnbindPath;
	    private string tooltipKeyBindPath;

	    public String ContentPlaceHolderId
		{
			get { return contentPlaceHolderId;}
			set { contentPlaceHolderId = value;}
		}


        public bool AllowFirstUnbind(string propertyName)
        {
            if (allowFirstUnbindFor == null)
                return false;

            propertyName = propertyName.ToLower();

            foreach (string key in allowFirstUnbindFor)
            {
                if (key.ToLower().Equals(propertyName))
                    return true;
            }
            
            return false;
        }

        public IList AllowFirstUnbindFor
	    {
            get { return allowFirstUnbindFor; }
            set { allowFirstUnbindFor = value; }
	    }

	    public IScopePathParser ScopePathParser
	    {
	        get { return scopePathParser; }
	        set { scopePathParser = value; }
	    }

	    public bool DoBind
	    {
	        get
	        {
                if (!String.IsNullOrEmpty(doBindPath))
                    return Converter.ToBoolean(scopePathParser.Parse(doBindPath).Value);
	            
	            return doBind;
	        }
	        set { doBind = value; }
	    }

	    public bool DoUnbind
	    {
	        get
	        {
                if (!String.IsNullOrEmpty(doUnbindPath))
                    return Converter.ToBoolean(scopePathParser.Parse(doUnbindPath).Value);
	            
	            return doUnbind;
	        }
	        set { doUnbind = value; }
	    }

	    public string DoBindPath
	    {
	        get { return doBindPath; }
	        set { doBindPath = value; }
	    }

	    public string DoUnbindPath
	    {
	        get { return doUnbindPath; }
	        set { doUnbindPath = value; }
	    }

	    public bool Visible
		{
			get { return visible; }
			set { visible = value; }
		}

		public bool Enabled
		{
			get { return enabled; }
			set { enabled = value; }
		}

		public IDataTranslator DataTranslator
		{
			get { return dataTranslator; }
			set { dataTranslator = value; }
		}

		public IDataTranslator DataParser
		{
			get { return dataParser; }
			set { dataParser = value; }
		}

	    public IDictionary PropertyDataTranslators
	    {
	        get { return propertyDataTranslators; }
	        set { propertyDataTranslators = value; }
	    }

	    public IDictionary PropertyDataParsers
	    {
	        get { return propertyDataParsers; }
	        set { propertyDataParsers = value; }
	    }
	    
	    public IDataTranslator GetDataTranslator(string property)
	    {
            if (propertyDataTranslators == null)
                return null; /*dataTranslator;*/

            foreach (String key in propertyDataTranslators.Keys)
            {
                if (key.ToLower().Equals(property.ToLower()))
                    return propertyDataTranslators[key] as IDataTranslator;
            }

            return null; /*dataTranslator;*/
	    }

        public IDataTranslator GetDataParser(string property)
        {
            if (propertyDataParsers == null)
                return null; /*dataParser;*/

            foreach (String key in propertyDataParsers.Keys)
            {
                if (key.ToLower().Equals(property.ToLower()))
                    return propertyDataParsers[key] as IDataTranslator;
            }

            return null; /*dataParser;*/
        }

	    public string CssClass
		{
			get { return cssClass; }
			set { cssClass = value; }
		}

		public Unit Width
		{
			get { return width; }
			set { width = value; }
		}

		public Unit Height
		{
			get { return height; }
			set { height = value; }
		}

		public string Id
		{
			get { return id; }
			set { id = value; }
		}

		public string ObjectName
		{
			get { return objectName; }
			set { objectName = value; }
		}


		public IDictionary Actions
		{
			get { return actions; }
			set { actions = value; }
		}

		public IList ExceptionHandlers
		{
			get { return exceptionHandlers; }
			set { exceptionHandlers = value; }
		}

		public IExceptionHandlerMatcher ExceptionHandlerMatcher
		{
			get { return exceptionHandlerMatcher; }
			set { exceptionHandlerMatcher = value; }
		}

		public IList RolesVisible
		{
			get { return rolesVisible; }
			set { rolesVisible = value; }
		}

		public IList RolesEnabled
		{
			get { return rolesEnabled; }
			set { rolesEnabled = value; }
		}

		public IPrincipalWrapper PrincipalWrapper
		{
			get { return principalWrapper; }
			set { principalWrapper = value; }
		}

		public IDictionary ClientAttributes
		{
			get { return clientAttributes; }
			set { clientAttributes = value; }
		}

		public IMessageManager MessageManager
		{
			get { return messageManager; }
			set { messageManager = value; }
		}

		public IImageManager ImageManager
		{
			get { return imageManager; }
			set { imageManager = value; }
		}

		public bool CausesValidation
		{
			get { return causesValidation; }
			set { causesValidation = value; }
		}

		public IList ValidatorWrappers
		{
			get { return validatorWrappers; }
			set { validatorWrappers = value; }
		}
	    
	    public string ValidationGroup
	    {
	        get
	        {
                return this.validationGroup;
	        }
	        set
	        {
                this.validationGroup = value;
	        }
	    }

		public string ExecutionContextPrefix
		{
			get
			{
//				if (executionContextPrefix != null && !string.Empty.Equals(executionContextPrefix))
//				{
//					return executionContextPrefix;
//				}
//				if (id != null && !string.Empty.Equals(id))
//				{
//					return id;
//				}
//				return objectName;
				return executionContextPrefix;
			}
			set {executionContextPrefix = value;}
		}

		public Type ControlType
		{
			get { return controlType; }
			set { controlType = value; }
		}
/*
		public string ImageUrl
		{
			get { return imageUrl; }
			set { imageUrl = value; }
		}
*/
		public IAction GetAction(string name)
		{
			return (IAction)(actions!=null?actions[name]:null);
		}

		public IExceptionHandler GetExceptionHandler(Exception exception)
		{
			if(exceptionHandlerMatcher != null && exceptionHandlers != null && exceptionHandlers.Count != 0)
			{
				return exceptionHandlerMatcher.Match(exception, exceptionHandlers);
			}
			return null;
		}

		public bool IsVisibleForPrincipal()
		{
            //if (IsEnabledForPrincipal())
            //    return true;

            if (principalWrapper == null || rolesVisible == null || rolesVisible.Count == 0)
            {
                return true;
            }

            foreach (string roleName in rolesVisible)
            {
                if (principalWrapper.IsInRole(roleName))
                {
                    return true;
                }
            }

            /*
             * This is not the same as write in the beginning of the method:
             * 
             * if (IsEnabledForPrincipal()) return true;
             * 
             * because if visible roles exist but a principle doesn't have permissions
             * to view and edit roles haven't been set then control should be disabled
             * 
             */
            if (rolesEnabled == null || rolesEnabled.Count == 0)
            {
                return false;
            }

            return IsEnabledForPrincipal();
		}

		public bool IsEnabledForPrincipal()
		{
			if(principalWrapper == null || rolesEnabled == null || rolesEnabled.Count == 0)
			{
				return true;
			}
			foreach(string roleName in rolesEnabled)
			{
				if(principalWrapper.IsInRole(roleName))
				{
					return true;
				}
			}
			return false;
		}


		public string Label
		{
			get { return label; }
			set { label = value; }
		}

		public string LabelKey
		{
			get { return this.labelKey!=null&&this.labelKey!=string.Empty?this.labelKey:ObjectName; }
			set { labelKey = value; }
		}


		public IDictionary Labels
		{
			set
			{
				labels = value;
				if(!labels.Contains("default"))
				{
					if(label != null && string.Empty != label)
					{
						labels["default"] = label;
					}
				}
				else
				{
					if(label == null || label == string.Empty)
					{
						label = (string)labels["default"];
					}
				}
			}
		}

		public string TextKey
		{
			get { return textKey; }
			set { textKey = value; }
		}

		public string GetLocalizedLabel()
		{
			return GetLocalizedLabel(label);
		}

		public string GetLocalizedLabel(string defaultValue)
		{
			return MessageManager.GetMessage(LabelKey, (defaultValue!=null&&string.Empty!=defaultValue?defaultValue:label));
		}

		public string GetLocalizedPostfixLabel(string postfix)
		{
			return GetLocalizedPostfixLabel(postfix, (postfix == null || postfix == string.Empty || postfix == "default"?label:null));
		}

		public string GetLocalizedPostfixLabel(string postfix, string defaultValue)
		{
			if(postfix == null || postfix == string.Empty ||postfix == "default")
			{
				return GetLocalizedLabel(defaultValue);
			}
 
			defaultValue = defaultValue!=null&&defaultValue!=string.Empty?defaultValue:labels!=null?(string)labels[postfix]:null;

			return MessageManager.GetMessage(LabelKey + "." + postfix, defaultValue);
			
		}

		public string GetLocalizedPrefixLabel(string prefix)
		{
			//return GetLocalizedPrefixLabel(prefix + "." + LabelKey, Label);
			return MessageManager.GetMessage(prefix + "." + LabelKey, Label);
		}

		public string GetLocalizedPrefixLabel(string prefix, string defaultValue)
		{
			return MessageManager.GetMessage(prefix + "." + LabelKey, defaultValue);
		}


		public virtual IConfiguration CreateFromTemplate()
		{
			ConstructorInfo constructorInfo = this.GetType().GetConstructor(new Type[]{});
			if(constructorInfo == null)
			{
				throw new ConfigurationErrorsException("unable to locate a null argument constructor");
			}

			GenericConfiguration template = (GenericConfiguration)constructorInfo.Invoke(new object[]{});
			template.actions = this.actions;
			template.exceptionHandlers = this.exceptionHandlers;
			template.exceptionHandlerMatcher = this.exceptionHandlerMatcher;
			template.rolesVisible = this.rolesVisible;
			template.rolesEnabled = this.rolesEnabled;
			template.principalWrapper = this.principalWrapper;
			template.clientAttributes = this.clientAttributes;
			template.messageManager = this.messageManager;
			template.imageManager = this.imageManager;
			template.controlType = this.controlType;
			template.label = this.label;
			template.labelKey = this.labelKey;
			template.labels = this.labels;
			template.executionContextPrefix = this.executionContextPrefix;
			template.textKey = this.textKey;
			template.width = this.width;
			template.height = this.height;
			template.cssClass = this.cssClass;
			template.dataParser = this.dataParser;
			template.dataTranslator = this.dataTranslator;

			return template;
		}


//		public string EntityPath
//		{
//			get { return entityPath; }
//			set { entityPath = value; }
//		}
//
//		public string BindDirection
//		{
//			get { return bindDirection; }
//			set { bindDirection = value; }
//		}
//
//		public IDictionary EntityPaths
//		{
//			get { return entityPaths; }
//			set { entityPaths = value; }
//		}


		public string VisibleBindPath
		{
			get { return visibleBindPath; }
			set { visibleBindPath = value; }
		}

		public string VisibleUnbindPath
		{
			get { return visibleUnbindPath; }
			set { visibleUnbindPath = value; }
		}

		public string VisiblePath
		{
			set
			{
				visibleBindPath=value;
				visibleUnbindPath=value;
			}
		}

		public string EnabledBindPath
		{
			get { return enabledBindPath; }
			set { enabledBindPath = value; }
		}

		public string EnabledUnbindPath
		{
			get { return enabledUnbindPath; }
			set { enabledUnbindPath = value; }
		}

		public string EnabledPath
		{
			set
			{
				enabledBindPath=value;
				enabledUnbindPath=value;
			}
		}

		public string TextBindPath
		{
			get { return textBindPath; }
			set { textBindPath = value; }
		}

		public string TextUnbindPath
		{
			get { return textUnbindPath; }
			set { textUnbindPath = value; }
		}

		public string TextKeyBindPath
		{
			get { return textKeyBindPath; }
			set { textKeyBindPath = value; }
		}

		public string TextKeyUnbindPath
		{
			get { return textKeyUnbindPath; }
			set { textKeyUnbindPath = value; }
		}

		public string TextPath
		{
			set
			{
				textBindPath=value;
				textUnbindPath=value;
			}
		}

		public string TextKeyPath
		{
			set
			{
				textKeyBindPath=value;
				textKeyUnbindPath=value;
			}
		}

		public string CausesValidationBindPath
		{
			get { return causesValidationBindPath; }
			set { causesValidationBindPath = value; }
		}

		public string CausesValidationUnbindPath
		{
			get { return causesValidationUnbindPath; }
			set { causesValidationUnbindPath = value; }
		}

		public string CausesValidationPath
		{
			set
			{
				causesValidationUnbindPath=value;
				causesValidationBindPath=value;
			}
		}

		public string ValueBindPath
		{
			get { return valueBindPath; }
			set { valueBindPath = value; }
		}

		public string ValueUnbindPath
		{
			get { return valueUnbindPath; }
			set { valueUnbindPath = value; }
		}
	
		public string ValuePath
		{
			set
			{
				valueBindPath=value;
				valueUnbindPath=value;
			}
		}        
	    
        public string ValidationGroupBindPath
        {
            get { return validationGroupBindPath; }
            set { validationGroupBindPath = value; }            
        }

        public string ValidationGroupUnbindPath
        {
            get { return validationGroupUnbindPath; }
            set { validationGroupUnbindPath = value; }   
        }

        public string ValidationGroupPath
        {
            set
            {
                validationGroupBindPath = value;
                validationGroupUnbindPath = value;
            }
        }

        public bool ReadOnly
        {
            get { return readOnly; }
            set { readOnly = value; }
        }

	    public string ReadOnlyBindPath
        {
            get { return readOnlyBindPath; }
            set { readOnlyBindPath = value; }
        }

        public string ReadOnlyUnbindPath
        {
            get { return readOnlyUnbindPath; }
            set { readOnlyUnbindPath = value; }
        }

        public string ReadOnlyPath
        {
            set
            {
                readOnlyBindPath = value;
                readOnlyUnbindPath = value;
            }
        }

	    public string ToolTip
	    {
            get { return toolTip; }
	        set { toolTip = value;}
	    }

	    public string ToolTipKey
	    {
	        get { return toolTipKey; }
	        set { toolTipKey=value; }
	    }

	    public string ToolTipKeyBindPath
	    {
	        get { return tooltipKeyBindPath; }
            set { tooltipKeyBindPath = value; }
	    }

	    public string ToolTipKeyUnbindPath
	    {
	        get { return tooltipKeyUnbindPath; }
            set { tooltipKeyUnbindPath = value; }
	    }

        public string ToolTipKeyPath
        {
            set
            {
                tooltipKeyBindPath = value;
                tooltipKeyUnbindPath = value;
            }
        }

	    public string ToolTipBindPath
	    {
	        get { return tooltipBindPath; }
            set { tooltipBindPath = value; }
	    }

	    public string ToolTipUnbindPath
	    {
	        get { return tooltipUnbindPath; }
            set { tooltipUnbindPath = value; }
	    }

        public string ToolTipPath
        {
            set
            {
                tooltipBindPath = value;
                tooltipUnbindPath = value;
            }
        }


	}
}
